/*  This file is part of -_-.

    -_- is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    -_- is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with -_-.  If not, see <http://www.gnu.org/licenses/>.

    Copyright 2012 Oliver Katz */

#ifndef __VISUAL_DISPLAY_ENGINE_H
#define __VISUAL_DISPLAY_ENGINE_H

#include <iostream>
#include "../layout_engine/layout_engine.h"
#include "../backend_opengl.h"

namespace sleepyface
{
	namespace visual
	{
		namespace display_engine
		{
			class DisplayBox
			{
			private:
				int width;
				int height;

			public:
				DisplayBox();
				DisplayBox(int w, int h);
				DisplayBox error(int c);
				int getWidth();
				int getHeight();
				bool empty();
				bool isError();
				int errorCode();
				int compare(DisplayBox d);
			};

			typedef DisplayBox *(*WidgetSizeCallback)(layout_engine::Widget *, DisplayBox *);
			typedef DisplayBox *(*WidgetRenderCallback)(layout_engine::Widget *, int, int, DisplayBox *);

			class WidgetRenderer
			{
			private:
				WidgetSizeCallback sizer;
				WidgetRenderCallback renderer;

			public:
				WidgetRenderer();
				WidgetRenderer(WidgetSizeCallback s, WidgetRenderCallback r);
				int bindSizer(WidgetSizeCallback s);
				int bindRenderer(WidgetRenderCallback r);
				DisplayBox requestSize(layout_engine::Widget w, DisplayBox hint);
				int render(layout_engine::Widget w, int x, int y, DisplayBox size);
			};

			typedef DisplayBox *(*ContainerHinterCallback)(layout_engine::Container *, DisplayBox *);
			typedef DisplayBox *(*ContainerSizeCallback)(layout_engine::Container *, DisplayBox *);
			typedef DisplayBox *(*ContainerRenderCallback)(layout_engine::Container *, int, int, DisplayBox *);

			class ContainerRenderer
			{
			private:
				ContainerSizeCallback sizer;
				ContainerHinterCallback hinter;
				ContainerRenderCallback renderer;

			public:
				ContainerRenderer();
				ContainerRenderer(ContainerSizeCallback s, ContainerHinterCallback h, ContainerRenderCallback r);
				int bindSizer(ContainerSizeCallback s);
				int bindRenderer(ContainerRenderCallback r);
				int bindHinter(ContainerHinterCallback h);
				DisplayBox requestSize(layout_engine::Container c, DisplayBox hint);
				vector<pair<DisplayBox, DisplayBox> > requestHints(layout_engine::Container c, DisplayBox size);
				int render(layout_engine::Container c, int x, int y, DisplayBox size);
			};

			class DisplayEngine
			{
			private:
				map<string, WidgetRenderer> widgetRenderers;
				map<string, ContainerRenderer> containerRenderers;
				map<string, pair<DisplayBox, DisplayBox> > coords;

			public:
				DisplayEngine();
				int addWidgetRenderer(string n, WidgetRenderer r);
				int addContainerRenderer(string n, ContainerRenderer r);
				int recursivelyRenderContainer(layout_engine::Container c, int x, int y, DisplayBox h);
				string getNameFromCoordinatesInContainer(layout_engine::Container c, int x, int y);
			};
		}
	}
}

#endif